package FrequentSequenceMining;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;

public class Data {
	private ArrayList<ArrayList<String> > sentences; //all sentences separated in words, sorted by length
	private TreeMap<String, Sequence> words; //list of all words and their associated sequences
	private ArrayList<Integer> lenSents; //number of sentences of each length: lenSents[0] = #sentences of length 1
	private static Data instance;
	
	private Data() {
		sentences = new ArrayList<ArrayList<String>>();
		words = new TreeMap<String, Sequence>();
		lenSents = new ArrayList<Integer>();
	}
	
	public static Data getInstance() {
		if(instance == null) {
			instance = new Data();
		}
		return instance;
	}

	public void readFile(String fileName) {
		try {
			File file = new File(fileName);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			
			HashMap<Integer, Integer> senLenHash = new HashMap<Integer, Integer>();
			int longSenLen = 0;
			String line = "";
			int lineNumber = 0;
			while ((line=bufferedReader.readLine()) != null) {
				
				line = line.toLowerCase();
				line = line.replace(",", "");
				line = line.replace(".", "");
				line = line.replace(":", "");
				line = line.replace(";", "");
				line = line.replace("\"", "");
				line = line.replace("  ", " ");
				
				ArrayList<String> tmpArrList = new ArrayList<String>();
				String [] strWordsOfSentences = line.split(" ");
				
				if(strWordsOfSentences.length > longSenLen) 
					longSenLen = strWordsOfSentences.length;
				
				if(senLenHash.containsKey(strWordsOfSentences.length)) {
					senLenHash.put(strWordsOfSentences.length, (Integer)senLenHash.get(strWordsOfSentences.length) +1);							
				}
				else
					senLenHash.put(strWordsOfSentences.length, 1);
					
				for(int i=0; i<strWordsOfSentences.length; i++) {
					tmpArrList.add(strWordsOfSentences[i]);
					
					 if(!words.containsKey(strWordsOfSentences[i])) {
						 Sequence s = new Sequence(strWordsOfSentences[i]);
						 s.addAppearance(lineNumber);
						 words.put(strWordsOfSentences[i],s);
					 }
					 else {
						 Sequence s = words.get(strWordsOfSentences[i]);
						 s.increaseSupport();
						 s.addAppearance(lineNumber);
					 }
						 
				}
				sentences.add(tmpArrList);
				lineNumber++;
			}
			
			bufferedReader.close();
			fileReader.close();
			
			copySenLens(senLenHash, longSenLen);
			//sortSentences(0, sentences.size()-1);
			
		}catch(Exception exp)
		{
			printFunc("Exp!!!>>>>> " + exp.toString());
		}
	}
	
	public void copySenLens(HashMap<Integer, Integer> paramSenLenHashMap, int paramLongSenLen)
	{
		for(int i = 1; i<= paramLongSenLen; i++) {
			
			//printFunc("key: " + i + " value: " + paramSenLenHashMap.get(i) + " bool: " + paramSenLenHashMap.containsKey(i));
						
			if(paramSenLenHashMap.containsKey(i))
				lenSents.add((Integer) paramSenLenHashMap.get(i));
			else
				lenSents.add(0);
		}
	}
	
	public void sortSentences(int low, int high) {
		int i = low, j = high;
		int pivot = sentences.get(low + (high-low)/2).size();
		

		while (i <= j) 
		{
			while (sentences.get(i).size() < pivot) 
			{
				i++;
			}
			while (sentences.get(j).size() > pivot) 
			{
				j--;
			}

			if (i <= j) 
			{
				exchange(i, j);
				i++;
				j--;
			}
		}
		
		if (low < j)
			sortSentences(low, j);
		if (i < high)
			sortSentences(i, high);
	}
	
	public void exchange(int i, int j)
	{
		ArrayList<String> tempArrList = sentences.get(i);
		sentences.set(i,sentences.get(j));
		sentences.set(j,tempArrList);
	} 

	public ArrayList<Sequence> getLengthOneSequences() {
		ArrayList<Sequence> toReturn = new ArrayList<Sequence>();
		
		for(String s:words.descendingKeySet()) {
			Sequence seq = words.get(s);
			if(seq.getSupport() >= getMinSupport()){
				toReturn.add(seq);
			}
		}
		return toReturn;
	}
	
	public int getTotalSentences() {
		return sentences.size();
	}
	
	public ArrayList<ArrayList<String>> getSentences() {
		return sentences;
	}
	
	public void printFunc(String msg) {
		System.out.println(">> " + msg);
	}

	public int getMinSupport() {
		return (int)(getTotalSentences()*SequenceList.MINFREQUENCY);
	}

	public Sequence getCorrespondingSequence(String word) {
		return words.get(word);
	}
}
